home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / misc / gms_pictures.lha / Pictures / PIC_Functions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-05  |  11.6 KB  |  392 lines

  1.  
  2. #include <proto/dpkernel.h>
  3. #include <system/all.h>
  4. #include <dpkernel/prefs.h>
  5. #include "defs.h"
  6.  
  7. /***********************************************************************************
  8. ** Internal: UnpackPicture()
  9. **
  10. ** Unpacks the BODY data to the Picture->Bitmap.  If the palettes or amount of
  11. ** colours do not match, the picture will be automatically remapped.
  12. */
  13.  
  14. LONG UnpackPicture(struct Picture *Picture, struct BMHD *BMHD,
  15.                    struct File *File, LONG *CMAP, LONG CAMG)
  16. {
  17.   struct Bitmap *Bitmap;
  18.   struct Bitmap *ILBMBitmap = NULL;
  19.   WORD   MaxWidth;
  20.   LONG   Colour;
  21.   WORD   i, y, j, ydest;
  22.   WORD   XRemainder, YRemainder, Domain;
  23.   LONG   AmtColours;
  24.   WORD   Height;
  25.   WORD   BPos;
  26.   BYTE   *DestPalette;
  27.   BYTE   *SrcPalette;
  28.   BYTE   *SrcBData;
  29.   BYTE   *DestBData;
  30.   BYTE   *Dest;
  31.   LONG   *Palette = NULL;
  32.   BYTE   *Buffer  = NULL;
  33.   APTR   BLTBase  = GVBase->BlitterBase;
  34.   LONG   ecode    = ERR_FAILED;
  35.  
  36.   DPrintF("UnpackPicture()","Unpacking ILBM picture to destination...");
  37.  
  38.   if (Picture->Options & IMG_RESIZE) {
  39.      DPrintF("UnpackPicture:","Note that the image will need to be resized.");
  40.   }
  41.  
  42.   DPrintF("3UnpackPicture:","Allocating an unpack buffer of %ld bytes.",UNPACKSIZE);
  43.  
  44.   if ((Buffer = AllocMemBlock(UNPACKSIZE, MEM_DATA)) IS NULL) {
  45.      goto exit;
  46.   }
  47.  
  48.   Bitmap     = Picture->Bitmap;
  49.   YRemainder = NULL;
  50.  
  51.   if ((Height = Bitmap->Height) > BMHD->Height) {
  52.      Height = BMHD->Height;
  53.   }
  54.  
  55.   /*** Calculate the amount of colours in the ILBM BMHD source. ***/
  56.  
  57.   if (CMAP) {
  58.      if ((BMHD->Depth < 1) OR (BMHD->Depth > 8)) {
  59.         DPrintF("!UnpackPicture:","Incorrect/Unsupported plane depth (%d).",BMHD->Depth);
  60.      }
  61.  
  62.      AmtColours = 1;
  63.      for (i=0; i < BMHD->Depth; i++) {
  64.          AmtColours *= 2;
  65.      }
  66.  
  67.      /* Build the palette here and use it in the ILBM Bitmap.  This is
  68.      ** necessary for ReadRGBPixel() functions which we use further down.
  69.      */
  70.  
  71.      if (Palette = AllocMemBlock((AmtColours * 4)+8,MEM_DATA)) {
  72.         Palette[0] = PALETTE_ARRAY;
  73.         Palette[1] = AmtColours;
  74.  
  75.         SrcPalette  = (BYTE *)CMAP;
  76.         DestPalette = ((BYTE *)Palette)+8;
  77.         for (i=0; i < AmtColours; i++) {
  78.            DestPalette[1] = SrcPalette[0];
  79.            DestPalette[2] = SrcPalette[1];
  80.            DestPalette[3] = SrcPalette[2];
  81.            DestPalette += 4;
  82.            SrcPalette  += 3;
  83.         }
  84.      }
  85.      else goto exit;
  86.   }
  87.  
  88.   DPrintF("3UnpackPicture:","Allocating dummy Bitmap.");
  89.  
  90.   if (!(ILBMBitmap = InitTags(NULL,
  91.        TAGS_BITMAP, NULL,
  92.        BMA_Width,   BMHD->Width,
  93.        BMA_Height,  1,
  94.        BMA_Planes,  BMHD->Depth,
  95.        BMA_Type,    ILBM,
  96.        BMA_Palette, Palette,
  97.        TAGEND))) {
  98.        goto exit;
  99.   }
  100.  
  101.   /*** Force remapping if colours or palettes are different ***/
  102.  
  103.   if (Bitmap->AmtColours != ILBMBitmap->AmtColours) {
  104.      Picture->Options |= IMG_REMAP;
  105.   }
  106.  
  107.   if ((Picture->Options & (IMG_REMAP|IMG_NOCOMPARE)) IS NULL) {
  108.      if (Bitmap->Palette) { /* Compare palettes */
  109.         for (i=2; i < (Bitmap->AmtColours+2); i++) {
  110.            if (Bitmap->Palette[i] != ILBMBitmap->Palette[i]) {
  111.               Picture->Options |= IMG_REMAP;
  112.               i = 30000; /* Terminate the loop */
  113.            }
  114.         }
  115.      }
  116.   }
  117.  
  118.   if (Picture->Options & IMG_REMAP) {
  119.      DPrintF("UnpackPicture:","Colour remapping for this Picture is in effect.");
  120.   }
  121.  
  122.   /*** Calculate some initial variables for the loop ***/
  123.  
  124.   if (Bitmap->Width < ILBMBitmap->Width) {
  125.      MaxWidth = Bitmap->Width;
  126.   }
  127.   else {
  128.      MaxWidth = ILBMBitmap->Width;
  129.   }
  130.   ydest = NULL;
  131.  
  132.   /* Begin the loop now.  Unpack one row at a time to the ILBM Bitmap
  133.   ** buffer, then copy the pixels from the buffer over to our destination.
  134.   */
  135.  
  136.   DebugOff();
  137.  
  138.   BPos = NULL;
  139.   Read(File, Buffer, UNPACKSIZE);
  140.  
  141.   for (y=0; y < Height; y++) {
  142.  
  143.      /*** Unpack the body data to our special ILBM Bitmap ***/
  144.  
  145.      if ((BMHD->Depth IS 8) AND (CAMG & OSV_HAM)) {
  146.         Dest = ((BYTE *)ILBMBitmap->Data) + (ILBMBitmap->ByteWidth * 2);
  147.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  148.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  149.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  150.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  151.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  152.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos);
  153.  
  154.         Dest = ILBMBitmap->Data;
  155.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  156.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos);
  157.      }
  158.      else {
  159.         Dest = ILBMBitmap->Data;
  160.         for (j=0; j < ILBMBitmap->Planes; j++) {
  161.            BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos);
  162.            Dest += ILBMBitmap->ByteWidth;
  163.         }
  164.      }
  165.  
  166.      /* Write the data out to the destination Bitmap.  If resizing,
  167.      ** we use the standard DrawPixel() and ReadPixel() routines.  Although
  168.      ** we could improve the speed in some parts, it is not too crucial.
  169.      */
  170.  
  171.      if ((Picture->Options & IMG_RESIZEX) AND (Bitmap->Width != ILBMBitmap->Width)) {
  172.         if (ILBMBitmap->Width > Bitmap->Width) { /*** Shrink Row ***/
  173.            XRemainder = NULL;
  174.            Domain = ILBMBitmap->Width - Bitmap->Width;
  175.            j = NULL;
  176.  
  177.            for (i=0; i < Bitmap->Width; i++) {
  178.               XRemainder += Domain;
  179.  
  180.               while (XRemainder >= Bitmap->Width) {
  181.                  XRemainder -= Bitmap->Width;
  182.                  j++;
  183.               }
  184.               Bitmap->DrawUCRPixel(Bitmap,i,ydest,ILBMBitmap->ReadUCRPixel(ILBMBitmap,j++,0));
  185.            }
  186.         }
  187.         else { /*** Expand Row ***/
  188.            XRemainder = NULL;
  189.            Domain = Bitmap->Width - ILBMBitmap->Width;
  190.            j = NULL;
  191.  
  192.            for (i=0; i < ILBMBitmap->Width; i++) {
  193.               Colour = ILBMBitmap->ReadUCRPixel(ILBMBitmap,i,0);
  194.               Bitmap->DrawUCRPixel(Bitmap,j++,ydest,Colour);
  195.               XRemainder += Domain;
  196.  
  197.               while (XRemainder >= ILBMBitmap->Width) {
  198.                  Bitmap->DrawUCRPixel(Bitmap,j++,ydest,Colour);
  199.                  XRemainder -= ILBMBitmap->Width;
  200.               }
  201.            }
  202.         }
  203.      }
  204.      else if (Picture->Options & IMG_REMAP) {
  205.         for (i=0; i < MaxWidth; i++) {
  206.             Bitmap->DrawUCRPixel(Bitmap,i,ydest,ILBMBitmap->ReadUCRPixel(ILBMBitmap,i,0));
  207.         }
  208.      }
  209.      else if ((Bitmap->Type IS PLANAR) OR (Bitmap->Type IS ILBM)) {
  210.         /* This routine takes advantage of the fact that PLANAR and ILBM
  211.         ** store pixels in sets of 8 per byte.
  212.         */
  213.  
  214.         SrcBData  = (BYTE *)ILBMBitmap->Data;
  215.         DestBData = ((BYTE *)Bitmap->Data) + (Bitmap->LineMod * ydest);
  216.         for (j=0; j < ILBMBitmap->Planes; j++) {
  217.            for (i=0; i < ((MaxWidth+15) & 0xFFF0)/8; i++) {
  218.               DestBData[i] = SrcBData[i];
  219.            }
  220.            SrcBData  += ILBMBitmap->ByteWidth;
  221.            DestBData += Bitmap->PlaneMod;
  222.         }
  223.      }
  224.      else if (Bitmap->Type IS CHUNKY8) {
  225.         DestBData = ((BYTE *)Bitmap->Data) + (Bitmap->ByteWidth * ydest);
  226.         for (i=0; i < MaxWidth; i++) {
  227.             DestBData[i] = ILBMBitmap->ReadUCPixel(ILBMBitmap,i,0); /* Convert ILBM to Chunky */
  228.         }
  229.      }
  230.      else { /* CHUNKY16 and TRUECOLOUR types require RGB to read from ILBM */
  231.         for (i=0; i < MaxWidth; i++) {
  232.             Bitmap->DrawUCRPixel(Bitmap,i,ydest,ILBMBitmap->ReadUCRPixel(ILBMBitmap,i,0));
  233.         }
  234.      }
  235.  
  236.      /*** Image Resizing Y Axis ***/
  237.  
  238.      if (Picture->Options & IMG_RESIZEY) {
  239.         if (Bitmap->Height < BMHD->Height) { /*** Shrink Down ***/
  240.            Domain      = BMHD->Height - Bitmap->Height;
  241.            YRemainder += Domain;
  242.            while (YRemainder >= Bitmap->Height) {
  243.               YRemainder -= Bitmap->Height;
  244.               BPos = SkipLine(BMHD, (BYTE *)Buffer, File, ILBMBitmap,BPos);
  245.            }
  246.         }
  247.         else if (Bitmap->Height > BMHD->Height) { /*** Expand ***/
  248.            Domain      = Bitmap->Height - BMHD->Height;
  249.            YRemainder += Domain;
  250.            while (YRemainder >= BMHD->Height) {
  251.               YRemainder -= BMHD->Height;
  252.               ydest++;
  253.               CopyLine(Bitmap,Bitmap,ydest-1,ydest,Bitmap->Width,0);
  254.            }
  255.         }
  256.      }
  257.      ydest++;
  258.   }
  259.  
  260.   ecode = ERR_OK;
  261.  
  262. exit:
  263.   DebugOn();
  264.   if (Buffer)     FreeMemBlock(Buffer);
  265.   if (ILBMBitmap) Free(ILBMBitmap);
  266.   if (Palette)    FreeMemBlock(Palette);
  267.   return(ecode);  
  268. }
  269.  
  270. /***********************************************************************************
  271. ** Internal: SkipLine()
  272. ** Short:    Skips a complete line of Buffer data.
  273. */
  274.  
  275. WORD SkipLine(struct BMHD *BMHD, BYTE *Buffer, struct File *File, struct Bitmap *ILBMBitmap, WORD BPos)
  276. {
  277.   WORD written;
  278.   BYTE num, j;
  279.  
  280.   if (BMHD->Pack) {
  281.      for (j=0; j < ILBMBitmap->Planes; j++) {
  282.         written = NULL;
  283.         while (written < ILBMBitmap->ByteWidth) {
  284.            num = Buffer[BPos++];
  285.            if (BPos >= UNPACKSIZE) {
  286.               BPos = NULL;
  287.               Read(File, Buffer, UNPACKSIZE);
  288.            }
  289.  
  290.            if (num >= 0) {
  291.               do {
  292.                  BPos++;
  293.                  if (BPos >= UNPACKSIZE) {
  294.                     BPos = NULL;
  295.                     Read(File, Buffer, UNPACKSIZE);
  296.                  }
  297.                  num--;
  298.                  written++;
  299.               } while (num >= 0);
  300.            }
  301.            else if (num != -128) {
  302.               num = -num;
  303.               BPos++;
  304.               if (BPos >= UNPACKSIZE) {
  305.                  BPos = NULL;
  306.                  Read(File, Buffer, UNPACKSIZE);
  307.               }
  308.  
  309.               do {
  310.                  written++;
  311.                  num--;
  312.               } while (num >= 0);
  313.            }
  314.         }
  315.      }
  316.   }
  317.   else {
  318.      for (j=0; j < ILBMBitmap->Planes; j++) {
  319.         for (num=0; num < ILBMBitmap->ByteWidth; num++) {
  320.            BPos++;
  321.            if (BPos >= UNPACKSIZE) {
  322.               BPos = NULL;
  323.               Read(File, Buffer, UNPACKSIZE);
  324.            }
  325.         }
  326.      }
  327.   }
  328.  
  329.   return(BPos);
  330. }
  331.  
  332. /***********************************************************************************
  333. ** Internal: UnpackPlane()
  334. ** Short:    Unpacks one plane of BODY data to the ILBMBitmap object.
  335. */
  336.  
  337. WORD UnpackPlane(struct BMHD *BMHD, struct File *File, struct Bitmap *ILBMBitmap, BYTE *Dest, BYTE *Buffer, WORD BPos)
  338. {
  339.   WORD written;
  340.   BYTE num, col;
  341.  
  342.   if (BMHD->Pack) {
  343.      written = NULL;
  344.      while (written < ILBMBitmap->ByteWidth) {
  345.         num = Buffer[BPos++];
  346.         if (BPos >= UNPACKSIZE) {
  347.            BPos = NULL;
  348.            Read(File, Buffer, UNPACKSIZE);
  349.         }
  350.  
  351.         if (num >= 0) {
  352.            do {
  353.               *Dest++ = Buffer[BPos++];
  354.               if (BPos >= UNPACKSIZE) {
  355.                  BPos = NULL;
  356.                  Read(File, Buffer, UNPACKSIZE);
  357.               }
  358.               num--;
  359.               written++;
  360.               if (written > ILBMBitmap->ByteWidth) return(BPos);
  361.            } while (num >= 0);
  362.         }
  363.         else if (num != -128) {
  364.            col = Buffer[BPos++];
  365.            if (BPos >= UNPACKSIZE) {
  366.               BPos = NULL;
  367.               Read(File, Buffer, UNPACKSIZE);
  368.            }
  369.  
  370.            do {
  371.               *Dest++ = col;
  372.               written++;
  373.               num++;
  374.               if (written > ILBMBitmap->ByteWidth) return(BPos);
  375.            } while (num <= 0);
  376.         }
  377.      }
  378.   }
  379.   else {
  380.      for (num=0; num < ILBMBitmap->ByteWidth; num++) {
  381.         *Dest++ = Buffer[BPos++];
  382.         if (BPos >= UNPACKSIZE) {
  383.            BPos = NULL;
  384.            Read(File, Buffer, UNPACKSIZE);
  385.         }
  386.      }
  387.   }
  388.  
  389.   return(BPos);
  390. }
  391.  
  392.